from flask import Flask
from flask_json import FlaskJSON, as_json
from flask_limiter import RateLimitExceeded

from app.error import ParameterError, IpFilterError, AuthRoleError, AuthPermissionError
from app.models import CommonResult


class HandlerGlobalException:
    """全局异常处理"""

    def __init__(self, app: Flask | None = None, json: FlaskJSON | None = None):
        if app is not None:
            self.init_app(app, json)

    def init_app(self, app: Flask, json: FlaskJSON) -> None:
        """全局异常处理初始化"""
        app.logger.debug('==> HandlerGlobalException...')

        # 表单参数校验异常
        @app.errorhandler(ParameterError)
        @as_json
        def parameter_error(error):
            if isinstance(error, ParameterError):
                return CommonResult(code=error.code, msg=str(error.message))

        # 404
        @app.errorhandler(404)
        @as_json
        def not_found(error):
            return CommonResult(code=404, data=str(error), msg='请求地址不存在')

        # 500
        @app.errorhandler(500)
        @as_json
        def internal_server_error(error):
            return CommonResult(code=500, data=str(error), msg='服务器内部错误')

        # 429 接口触发限流：RateLimitExceeded
        @app.errorhandler(RateLimitExceeded)
        @as_json
        def ratelimit_handler(e):
            if isinstance(e, RateLimitExceeded):
                return CommonResult(code=429, data=f"{e.description}", msg='请求太快，请等一会儿。')

        # 403 IP拦截：IpFilterError
        @app.errorhandler(IpFilterError)
        @as_json
        def ratelimit_handler(e):
            if isinstance(e, IpFilterError):
                return CommonResult(code=403, msg=f"{e.message}")

        # 角色验证失败
        @app.errorhandler(AuthRoleError)
        @as_json
        def auth_role_error_handler(e):
            if isinstance(e, AuthRoleError):
                return CommonResult(code=403, msg=f"无权限访问，无对应角色")

        # 权限验证失败
        @app.errorhandler(AuthPermissionError)
        @as_json
        def auth_permission_error_handler(e):
            if isinstance(e, AuthPermissionError):
                return CommonResult(code=403, msg=f"无权限访问，无对应权限")

        # json格式化失败
        @json.invalid_json_error
        @as_json
        def invalid_json_error(error):
            error_msg = app.config.get('JSON_DECODE_ERROR_MESSAGE')
            return CommonResult(code=500, data=str(error), msg=error_msg)
